/*******************************************************************************
 * Copyright (c) 2012 Alexandr Tsvetkov.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Alexandr Tsvetkov - initial API and implementation
 * 
 * Project:
 *     TAO Library
 * 
 * File name:
 *     HtmlParserQuick.java
 *     
 * License agreement:
 *
 * 1. This code is published AS IS. Author is not responsible for any damage that can be
 *    caused by any application that uses this code.
 * 2. Author does not give a garantee, that this code is error free.
 * 3. This code can be used in NON-COMMERCIAL applications AS IS without any special
 *    permission from author.
 * 4. This code can be modified without any special permission from author IF AND ONLY IF
 *    this license agreement will remain unchanged.
 * 5. SPECIAL PERMISSION for this code usage in COMMERCIAL application SHOULD be obtained
 *    from author.
 ******************************************************************************/
package ua.at.tsvetkov.parsers;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

import ua.at.tsvetkov.util.Log;

/**
 * Легкий парсер для HTML и XML содержимого веб страницы. Уменьшает время обработки приблизительно на треть по сравнению с парсером <b>HtmlParser</b> за счет отсутсвия проверки корректности обработки
 * строк (проверки на нулевую длинну и <code>null</code>). Рекомендуется использовать после того, как отладили код при помощи парсера <b>HtmlParser</b> путем замены последнего в коде на данный класс.
 * 
 * @author A.Tsvetkov 2010 http://tsvetkov.at.ua mailto:al@ukr.net
 */

public class HtmlParserQuick {

	public static final String		WINDOWS_1251	= "windows-1251";
	public static final String		UTF_8				= "utf-8";

	private String						charset			= UTF_8;
	private InputStreamReader		br					= null;
	private URL							url				= null;
	private BufferedReader			in					= null;
	private URLConnection			connection		= null;
	private InputStream				is					= null;
	private String						urlStr			= "";
	private String						lastLine;
	private long						time;

	/**
	 * Создает парсер для обработки материала выдаваемого по ссылке в определенной кодировке
	 * 
	 * @param urlStr ссылка на материал
	 * @param charset кодировка (WINDOWS_1251, UTF_8)
	 */
	public HtmlParserQuick(String urlStr, String charset) {
		this.urlStr = urlStr;
		this.charset = charset;
	}

	/**
	 * Создает парсер для обработки материала выдаваемого по ссылке в кодировке UTF-8
	 * 
	 * @param urlStr ссылка на материал
	 */
	public HtmlParserQuick(String urlStr) {
		this.urlStr = urlStr;
	}

	/**
	 * Создает соединение с выходом по таймауту
	 * 
	 * @param timeout время таймаута в миллисекундах
	 * @return true если соединение успешно
	 * @throws IOException
	 */
	public void connect(int timeout) throws IOException {
		time = System.currentTimeMillis();
		url = new URL(urlStr);
		connection = (URLConnection) url.openConnection();
		connection.setConnectTimeout(timeout);
		is = connection.getInputStream();
		br = new InputStreamReader(is, charset);
		in = new BufferedReader(br);
	}

	/**
	 * Закрывает соединение парсера
	 * 
	 * @return true если закрытие успешно
	 * @throws IOException
	 */
	public void close() throws IOException {
		in.close();
		br.close();
		is.close();
		Log.v("Parsing time " + (System.currentTimeMillis() - time));
	}

	/**
	 * Читает содержимое до тех пор, пока в содержимом не обнаружится искомая строка.
	 * 
	 * @param stringForSearch строка для поиска
	 * @return строку в которой есть искомая строка
	 * @throws IOException
	 */
	public String search(String stringForSearch) throws IOException {
		String st = "";
		while (!st.contains(stringForSearch)) {
			st = in.readLine();
			lastLine = st;
		}
		return st;
	}

	/**
	 * Читает содержимое до тех пор, пока в содержимом не обнаружатся начальная и конечная подстроки. Возвращает строку лежащую между ними.
	 * 
	 * @param stStart начальная подстрока
	 * @param stEnd конечная подстрока
	 * @return подстрока заключенная между начальной и конечной подстроками
	 * @throws IOException
	 * @throws IndexOutOfBoundsException
	 * @throws NullPointerException
	 */
	public String searchSubstring(String stStart, String stEnd) throws IndexOutOfBoundsException, NullPointerException, IOException {
		String st = "";
		while (!st.contains(stStart) && !st.contains(stEnd)) {
			st = in.readLine();
			lastLine = st;
		}
		return getSubstring(st, stStart, stEnd);
	}

	/**
	 * Читает содержимое до тех пор, пока в содержимом не обнаружатся искомая подстрока - маркер. Возвращает строку лежащую между начальной и конечной подстроками.
	 * 
	 * @param marker маркер - подстрока для поиска
	 * @param stStart начальная подстрока
	 * @param stEnd конечная подстрока
	 * @return подстрока заключенная между начальной и конечной подстроками
	 * @throws IndexOutOfBoundsException
	 * @throws NullPointerException
	 * @throws IOException
	 */
	public String searchMarkerAndGetSubstring(String marker, String stStart, String stEnd) throws IndexOutOfBoundsException, NullPointerException, IOException {
		String st = search(marker);
		return getSubstring(st, stStart, stEnd);
	}

	/**
	 * Читает следующую строку
	 * 
	 * @return прочитанная строка
	 * @throws IOException
	 */
	public String readLine() throws IOException {
		String st = "";
		st = in.readLine();
		lastLine = st;
		return st;
	}

	/**
	 * Возвращает последнюю прочтенную строку
	 * 
	 * @return последняя прочитанная строка
	 */
	public String getLastLine() {
		return lastLine;
	}

	/**
	 * Анализирует переданную строку st и возвращает подстроку, заключенную между строками stStart и stEnd
	 * 
	 * @param st строка для анализа
	 * @param stStart начальный текст ограничивающий нужную подстроку слева
	 * @param stEnd конечный текст ограничивающий нужную подстроку справа
	 * @return искомая подстрока
	 * @throws IndexOutOfBoundsException
	 * @throws NullPointerException
	 */
	public String getSubstring(String st, String stStart, String stEnd) throws IndexOutOfBoundsException, NullPointerException {
		return st.substring(st.indexOf(stStart) + stStart.length(), st.indexOf(stEnd));
	}

}
